home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 8
/
Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso
/
Aminet
/
mus
/
play
/
tracker_4_31.lzh
/
tracker
/
Unix
/
ui.c
Wrap
C/C++ Source or Header
|
1995-05-15
|
10KB
|
552 lines
/* unix/ui.c
vi:ts=3 sw=3:
*/
/* Set terminal discipline to non blocking io and such.
*/
/* $Id: ui.c,v 4.16 1995/05/15 12:20:16 espie Exp espie $
* $Log: ui.c,v $
* Revision 4.16 1995/05/15 12:20:16 espie
* *** empty log message ***
*
* Revision 4.15 1995/05/12 20:41:31 espie
* Added audio_ui call.
*
* Revision 4.14 1995/05/12 13:53:47 espie
* New synchronization.
*
* Revision 4.13 1995/05/11 12:05:05 espie
* Old code trimmed away.
*
* Revision 4.12 1995/03/17 00:32:53 espie
* PREF XTERM code.
*
* Revision 4.11 1995/03/11 23:06:51 espie
* Display everything in titlebars for xterms.
*
* Revision 4.10 1995/03/06 23:36:30 espie
* Proper color patch.
*
* Revision 4.9 1995/03/03 14:24:40 espie
* Color fixed.
*
* Revision 4.8 1995/02/27 14:26:34 espie
* Cleaned up by Rolf Grossmann.
*
* Revision 4.7 1995/02/26 23:08:55 espie
* POSIX_CONFORMANT.
*
* Revision 4.6 1995/02/24 15:40:38 espie
* Removed all dependencies from show (cached PREF_SHOW) and
* fixed a small display bug therefore.
*
* Revision 4.5 1995/02/21 17:59:26 espie
* Internal problem: bad log with rcs.
*
* Revision 4.4 1995/02/08 13:47:35 espie
* *** empty log message ***
*
* Revision 4.3 1995/01/28 09:56:53 espie
* Port to FreeBSD/NeXTstep.
*
* Revision 4.2 1995/01/28 09:23:38 espie
* Support for old bsd io discipline (NeXT)
*
*
* Revision 4.0 1994/01/11 18:02:31 espie
* Major change: lots of new calls.
* Stupid termio bug: shouldn't restore term to sanity if we don't
* know what sanity is. For instance, if we haven't modified anything.
* cflags interpreted correctly.
* Hsavolai fix.
* Added bg/fg test.
*/
#include <sys/ioctl.h>
#include <signal.h>
#include "defs.h"
#include "extern.h"
#include "tags.h"
#include "prefs.h"
extern char *VERSION;
#ifdef USE_TERMIOS
#include <sys/termios.h> /* this should work on all posix hosts */
#endif
#ifdef USE_SGTTY /* only NeXt does, currently */
#include <sgtty.h>
#include <fcntl.h>
#endif
#ifdef __hpux
#include <sys/bsdtty.h>
#endif
LOCAL void nonblocking_io P((void));
LOCAL void sane_tty P((void));
LOCAL void (*INIT)P((void)) = nonblocking_io;
/* poor man's timer */
LOCAL int current_pattern;
LOCAL int count_pattern, count_song;
#define SMALL_DELAY 75
/* do not define any stdio routines if it's known not to work */
#ifdef stub_only
int run_in_fg()
{
return TRUE;
}
LOCAL void sane_tty()
{
}
LOCAL struct tag end_marker;
struct tag *get_ui()
{
end_marker.type = TAG_END;
return &end_marker;
}
#else
#ifdef USE_SGTTY
LOCAL struct sgttyb sanity;
LOCAL struct sgttyb *psanity = 0;
#endif
#ifdef USE_TERMIOS
LOCAL struct termios sanity;
LOCAL struct termios *psanity = 0;
#endif
LOCAL int is_fg;
/* signal handler */
LOCAL void goodbye(sig)
int sig;
{
static char buffer[25];
char *pter = buffer;
if (get_pref_scalar(PREF_COLOR))
pter = write_color(pter, 0);
sprintf(pter, "Signal %d", sig);
end_all(pter);
}
LOCAL void abort_this(sig)
int sig;
{
end_all("Abort");
}
#ifdef SIGTSTP
LOCAL void suspend(sig)
int sig;
{
static char buffer[25];
char *buf = buffer;
if (get_pref_scalar(PREF_COLOR))
buf = write_color(buf, 0);
*buf = 0;
puts(buf);
fflush(stdout);
sane_tty();
signal(SIGTSTP, SIG_DFL);
kill(0, SIGTSTP);
}
#endif
int run_in_fg()
{
int val;
/* this should work on every unix */
if (!isatty(fileno(stdin)) || !isatty(fileno(stdout)))
return FALSE;
/* real check for running in foreground */
if (ioctl(fileno(stdin), TIOCGPGRP, &val))
return FALSE;
#ifdef IS_POSIX
if (val == getpgrp())
#else
if (val == getpgrp(0))
#endif
return TRUE;
else
return FALSE;
}
/* if_fg_sane_tty():
* restore tty modes, _only_ if running in foreground
*/
LOCAL void if_fg_sane_tty()
{
if (run_in_fg())
sane_tty();
}
LOCAL void switch_mode()
{
#ifdef USE_SGTTY
struct sgttyb zap;
int tty;
#endif
#ifdef USE_TERMIOS
struct termios zap;
#endif
#ifdef SIGTSTP
signal(SIGTSTP, suspend);
#endif
signal(SIGCONT, switch_mode);
signal(SIGINT, goodbye);
signal(SIGQUIT, goodbye);
signal(SIGUSR1, abort_this);
if (run_in_fg())
{
#ifdef USE_SGTTY
tty = fileno(stdin);
fcntl(tty, F_SETFL, fcntl(tty, F_GETFL, 0) | FNDELAY);
ioctl(tty, TIOCGETP, &zap);
zap.sg_flags |= CBREAK;
zap.sg_flags &= ~ECHO;
ioctl(tty, TIOCSETP, &zap);
#endif
#ifdef USE_TERMIOS
tcgetattr(fileno(stdin), &zap);
zap.c_cc[VMIN] = 0; /* can't work with old */
zap.c_cc[VTIME] = 0; /* FreeBSD versions */
zap.c_lflag &= ~(ICANON|ECHO|ECHONL);
tcsetattr(fileno(stdin), TCSADRAIN, &zap);
#endif
is_fg = TRUE;
}
else
is_fg = FALSE;
}
/* nonblocking_io():
* try to setup the keyboard to non blocking io
*/
LOCAL void nonblocking_io()
{
#if 0 /* BROKEN */
/* try to renice our own process to get more cpu time */
if (nice(-15) == -1)
nice(0);
#endif
if (!psanity)
{
psanity = &sanity;
#ifdef USE_SGTTY
ioctl(fileno(stdin), TIOCGETP, psanity);
#endif
#ifdef USE_TERMIOS
tcgetattr(fileno(stdin), psanity);
#endif
}
switch_mode();
at_end(if_fg_sane_tty);
}
/* sane_tty():
* restores everything to a sane state before returning to shell */
LOCAL void sane_tty()
{
#ifdef USE_SGTTY
ioctl(fileno(stdin), TIOCSETP, psanity);
#endif
#ifdef USE_TERMIOS
tcsetattr(fileno(stdin), TCSADRAIN, psanity);
#endif
}
LOCAL int may_getchar()
{
char buffer;
INIT_ONCE;
if (run_in_fg() && !is_fg)
switch_mode();
if (run_in_fg() && read(fileno(stdin), &buffer, 1))
return buffer;
return EOF;
}
LOCAL struct tag result[2];
struct tag *get_ui()
{
int c;
result[0].type = TAG_END;
result[1].type = TAG_END;
count_pattern++;
count_song++;
switch(c = may_getchar())
{
case 'n':
result[0].type = UI_NEXT_SONG;
break;
case 'p':
if (count_song > SMALL_DELAY)
result[0].type = UI_RESTART;
else
result[0].type = UI_PREVIOUS_SONG;
count_song = 0;
break;
case 'x':
case 'e':
case 'q':
result[0].type = UI_QUIT;
break;
case 's':
result[0].type = UI_SET_BPM;
result[0].data.scalar = 50;
break;
case 'S':
result[0].type = UI_SET_BPM;
result[0].data.scalar = 60;
break;
case '>':
result[0].type = UI_JUMP_TO_PATTERN;
result[0].data.scalar = current_pattern + 1;
break;
case '<':
result[0].type = UI_JUMP_TO_PATTERN;
result[0].data.scalar = current_pattern;
if (count_pattern < SMALL_DELAY)
result[0].data.scalar--;
break;
case '?':
set_pref_scalar(PREF_SHOW, !get_pref_scalar(PREF_SHOW));
if (get_pref_scalar(PREF_SHOW))
putchar('\n');
break;
default:
audio_ui(c);
break;
}
return result;
}
#endif
void notice(s)
char *s;
{
fprintf(stderr, "%s\n", s);
}
void status(s)
char *s;
{
if (run_in_fg())
{
if (s)
{
puts(s);
}
else
putchar('\n');
}
}
LOCAL char title[25];
void song_title(s)
char *s;
{
strncpy(title, s, 25);
count_song = 0;
}
LOCAL char scroll_buffer[200];
GENERIC begin_info(title)
char *title;
{
if (run_in_fg())
return scroll_buffer;
else
return 0;
}
void infos(handle, s)
GENERIC handle;
char *s;
{
if (handle)
printf(s);
}
void info(handle, line)
GENERIC handle;
char *line;
{
if (handle)
puts(line);
}
void end_info(handle)
GENERIC handle;
{
if (handle)
fflush(stdout);
}
LOCAL char *last_result = 0;
LOCAL int ntracks;
void set_number_tracks(n)
int n;
{
ntracks = n;
}
LOCAL void clear_scroll(temp)
char *temp;
{
int i;
if (get_pref_scalar(PREF_COLOR))
{
for (i = 0; i * 2 < ntracks; i++)
{
strcpy(temp, " ");
temp = write_color(temp + 20, 0);
*temp++ = '|';
}
*temp++ = '|';
for (i = 0; i * 2 < ntracks; i++)
{
strcpy(temp, " ");
temp = write_color(temp + 20, 0);
*temp++ = '|';
}
}
else
{
for (i = 0; i * 2 < ntracks; i++)
{
strcpy(temp, " |");
temp += 14;
}
*temp++ = '|';
for (i = 0; i * 2 < ntracks; i++)
{
strcpy(temp, " |");
temp += 14;
}
}
*temp = '\0';
}
char *new_scroll()
{
last_result = 0;
if (run_in_fg())
last_result = malloc(200);
if (last_result)
clear_scroll(last_result);
return last_result;
}
LOCAL void do_scroll(char *line)
{
if (run_in_fg())
{
puts(line);
fflush(stdout);
free(line);
}
}
void scroll()
{
if (last_result)
sync_audio(do_scroll, last_result);
}
LOCAL void do_display_pattern(int *thingy)
{
int current, total, real;
current = thingy[0];
total = thingy[1];
real = thingy[2];
free(thingy);
if (run_in_fg())
{
if (get_pref_scalar(PREF_XTERM))
{
if (get_pref_scalar(PREF_SHOW))
{
int i;
for (i = 0; i < ntracks; i++)
printf("--------------");
printf("\033]2;tracker %s %3d/%3d[%3d] %s\007\n", VERSION,
current, total, real, title);
}
else
{
printf("\033]2;tracker %s %3d/%3d %s\007", VERSION,
current, total, title);
fflush(stdout);
}
}
else
{
if (get_pref_scalar(PREF_SHOW))
printf("\n%3d/%3d[%3d] %s\n", current, total, real, title);
else
printf("%3d/%3d\b\b\b\b\b\b\b", current, total);
fflush(stdout);
}
}
current_pattern = current;
count_pattern = 0;
}
void display_pattern(current, total, real)
int current, total, real;
{
int *thingy;
thingy = malloc(sizeof(int)*3);
thingy[0] = current;
thingy[1] = total;
thingy[2] = real;
sync_audio(do_display_pattern, thingy);
}
int checkbrk()
{
return FALSE;
}